package controller;

//mgas138 ru5pX2St8qk8
//therockerline yb2xr6Xv7ra9
//danipostemail xc2HH5Fj4AK5
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Date;
import java.util.Vector;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import model.Database;
import model.Evento;
import model.Notifica;
import model.SearchEvent;
import view.AdminContactView;
//import personalize.lookandfeel2;
import view.ContactProp;
import view.CreateEvent;
import view.Home;
import view.HomeCalendar;
import view.HomeContact;
import view.Login;
import view.Menu;
import view.ModifyAccount;
import view.ModifyEvent;
import view.Registration;
import view.SplashScreen;

public class Engine {
	public static Database modelloDb;
	public static Vector<ContactProp> cntProp = new Vector<ContactProp>();
	public static int activeCntProp;
	public final static String LoAD = "resource"+File.separatorChar+File.separatorChar+"LoAD.png";
	public final static Image immaginelog = Toolkit.getDefaultToolkit().getImage(Engine.LoAD);

	public static void main(String[] args) {
		new Engine();
	}

	public Engine() {
		new SplashScreen();
	}

	public static void closeDB() {
		Database.closeDB();
	}

	public static JLabel setImage(Path image, int w, int h) {
		ImageIcon img = resizeImage(image.toString(), w, h);
		// System.out.println("set image(path): "+image.toString());
		JLabel panel = new JLabel(img);
		panel.setVisible(true);
		return panel;
	}

	public static JLabel setImage(String image, int w, int h) {
		if (image.contains("SplashScreen") || image.contains("sex_")
				|| image.contains("add_photo.png") || image.contains("search.jpg") || image.contains("plus.png"))
			image = "resource" + File.separatorChar + File.separatorChar
			+ image;
		else
			switch (Database.USER){
			case "load14":{ image = "D:"+ File.separatorChar + File.separatorChar
					+"drop"+ File.separatorChar+ File.separatorChar
					+"Dropbox"+ File.separatorChar+ File.separatorChar
					+"resource" + File.separatorChar+ File.separatorChar
					+"profile_img" + File.separatorChar+ File.separatorChar
					+ image;
			break;
			}
			case "root":{
				image = "resource" + File.separatorChar+ File.separatorChar
						+ "profile_img" + File.separatorChar+ File.separatorChar
						+ image;
				break;
			}
			}
		// System.out.println("set image(image): "+image);
		ImageIcon img;
		img = resizeImage(image, w, h);
		JLabel panel = new JLabel(img);
		panel.setVisible(true);
		return panel;
	}

	public static JLabel setEventImage(String image, int w, int h) {
		image = "resource" + File.separatorChar + File.separatorChar
				+ "event_img" + File.separatorChar + File.separatorChar + image
				+ ".gif";
		// System.out.println(image);
		ImageIcon img = resizeImage(image, w, h);
		JLabel panel = new JLabel(img);
		panel.setVisible(true);
		return panel;
	}

	public static ImageIcon resizeImage(String filePath, int w, int h) {
		BufferedImage bsrc = null, bdest;
		ImageIcon theIcon = null;
		//System.out.println(filePath);
		// scale the image
		try {
			bsrc = ImageIO.read(new File(filePath));
			bdest = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
			Graphics2D g = bdest.createGraphics();
			AffineTransform at = AffineTransform.getScaleInstance((double) w / bsrc.getWidth(), (double) h / bsrc.getHeight());
			g.drawRenderedImage(bsrc, at);
			// add the scaled image
			theIcon = new ImageIcon(bdest);
		} catch (Exception e) {
			try {
				bsrc = ImageIO.read(new File("resource" + File.separatorChar + File.separatorChar+ "not_found.jpg"));
				bdest = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
				Graphics2D g = bdest.createGraphics();
				AffineTransform at = AffineTransform.getScaleInstance((double) w / bsrc.getWidth(), (double) h / bsrc.getHeight());
				g.drawRenderedImage(bsrc, at);
				// add the scaled image
				theIcon = new ImageIcon(bdest);
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				//e1.printStackTrace();
			}
			//e.printStackTrace();
		}

		return theIcon;
	}

	public static void copyImageInResource(File file) {
		try {
			String nomefile = Database.Utente.getPhoto();
			File copyFile = null;
			switch (Database.USER){
			case "load14":{
				copyFile = new File("D:"+ File.separatorChar + File.separatorChar
						+"drop"+ File.separatorChar+ File.separatorChar
						+"Dropbox"+ File.separatorChar+ File.separatorChar
						+"resource" + File.separatorChar+ File.separatorChar
						+"profile_img" + File.separatorChar+ File.separatorChar
						+ nomefile);
				break;
			}
			case "root":{
				copyFile = new File("resource" + File.separatorChar
						+ File.separatorChar + "profile_img" + File.separatorChar
						+ File.separatorChar + nomefile);
				break;
			}
			}
			// copio il file nella cartella resource\profile_img
			OutputStream out = new FileOutputStream(copyFile);
			Files.copy(file.toPath(), out);
		} catch (FileNotFoundException e) {
			//e.printStackTrace();
		} catch (IOException e) {
			//e.printStackTrace();
		}
	}

	public static void removeImage() {
		if (!Database.Utente.getPhoto().contains("sex_m.gif")
				|| !Database.Utente.getPhoto().contains("sex_f.gif"))
			try {
				File file = null;
				switch (Database.USER){
				case "load14":{
					file = new File("D:"+ File.separatorChar + File.separatorChar
							+"drop"+ File.separatorChar+ File.separatorChar
							+"Dropbox"+ File.separatorChar+ File.separatorChar
							+"resource" + File.separatorChar+ File.separatorChar
							+"profile_img" + File.separatorChar+ File.separatorChar
							+ Database.Utente.getPhoto());
					break;
				}
				case "root":{
					file = new File("resource" + File.separatorChar
							+ File.separatorChar + "profile_img" + File.separatorChar
							+ File.separatorChar + Database.Utente.getPhoto());
					break;
				}
				}
				/*if (*/file.delete();/*)
					System.out.println(file.getName() + " is deleted!");
				else
					System.out.println("Delete operation is failed.");
				 */
			} catch (Exception e) {
				//e.printStackTrace();
			}
	}

	public static void startModel() {
		modelloDb = new Database();

	}

	public static void startLogin() {
		new Login();
	}

	public static void startHome() {
		new Home();
	}

	public static void restartHome(String view) {
		switch (view) {
		case "CreateEvent":
			CreateEvent.stopCreateEvent();
			break;
		case "ModifyEvent":
			ModifyEvent.stopModifyEvent();
			break;
		case "account":
			ModifyAccount.stopModifyAccount();
			break;
		case "closeContactProp": {
			for (int j = 0; j < cntProp.size(); j++)
				if (cntProp.get(j).acc_id == activeCntProp) {
					cntProp.get(j).stopContactProp(cntProp.get(j).CP);
					cntProp.remove(j);
					break;
				}
			break;
		}
		case "admin": {
			AdminContactView.stopAdminContactView();
			HomeContact.restartHomeContact();
			break;
		}
		}
		Home.restart();
	}

	public static void restartLogin(boolean flag) {
		if (flag)
			Registration.stopRegistration(!flag);
		Login.restart();
	}

	public static void validateLogin(String username, String password) {
		if (!Database.validateLogin(username, password))
			Login.allertInvalidUsernameOrPassword();
		else {
			Login.stopLogin();
			startHome();
		}
	}

	public static void validateModify() {
		String pass = ModifyAccount.passtxt.getText();
		String nome = ModifyAccount.firstname.getText();
		String cogn = ModifyAccount.secondname.getText();
		boolean flag = true;
		if (pass.length() < 4
				|| ModifyAccount.passtxt.getForeground() == Color.lightGray) {
			ModifyAccount.allertInvalidPassword();
			flag = false;
		}
		if (nome.length() <=1
				|| ModifyAccount.firstname.getForeground() == Color.lightGray) {
			ModifyAccount.allertInvalidName();
			flag = false;
		}
		if (cogn.length() <=1
				|| ModifyAccount.secondname.getForeground() == Color.lightGray) {
			ModifyAccount.allertInvalidSurname();
			flag = false;
		}
		if (flag) {
			ModifyAccount.confirmTempAccountProp(true);
			Database.updateAccountOnDB(); // user è un nome disponibile e si può
			// procedere con l'inserimento nel
			// db
			Database.Utente.uppdater();
			restartHome("account");
		}
	}

	@SuppressWarnings("deprecation")
	public static void validateEvent(int id) {
		String nome = CreateEvent.nome.getText();
		String luogo = CreateEvent.luogo.getText();
		String desc = CreateEvent.desc.getText();
		String naal = null;
		boolean flag = true;
		if (nome.isEmpty() || nome == naal
				|| CreateEvent.nome.getForeground() == Color.lightGray) {
			CreateEvent.allertInvalidName();
			flag = false;
		}
		if (luogo.isEmpty() || luogo == naal
				|| CreateEvent.luogo.getForeground() == Color.lightGray) {
			CreateEvent.allertInvalidLuogo();
			flag = false;
		}
		if (desc.isEmpty() || desc == naal
				|| CreateEvent.desc.getForeground() == Color.lightGray) {
			CreateEvent.allertInvalidDesc();
			flag = false;
		}
		if (Database.Utente.getLevel() != 512) {
			Date d = CreateEvent.cal.getDate();
			int giorno = d.getDate();
			int mese = d.getMonth() + 1;
			int anno = d.getYear() + 1900;
			// System.out.println("Data cal:"+giorno+"/"+mese+"/"+anno+" Data odierna:"+HomeCalendar.thisday+"/"+(HomeCalendar.thisMonth+1)+"/"+HomeCalendar.thisYear);
			if (anno <= HomeCalendar.thisYear)
				if (mese <= (HomeCalendar.thisMonth + 1))
					if (giorno <= HomeCalendar.thisday) {
						CreateEvent.allertInvalidDate();
						flag = false;
					}
		}
		if (flag) {
			Database.Evento.insertEventoOnDb();
			HomeCalendarObserver.obs.uppdater();
			SearchEvent.evn.uppdater();
			Engine.restartHome("CreateEvent");
		}
	}

	@SuppressWarnings("deprecation")
	public static void validateModifyEvent(int id) {
		String nome = ModifyEvent.nome.getText();
		String luogo = ModifyEvent.luogo.getText();
		String desc = ModifyEvent.desc.getText();
		String naal = null;
		boolean flag = true;
		if (nome.isEmpty() || nome == naal
				|| ModifyEvent.nome.getForeground() == Color.lightGray) {
			ModifyEvent.allertInvalidName();
			flag = false;
		}
		if (luogo.isEmpty() || luogo == naal
				|| ModifyEvent.luogo.getForeground() == Color.lightGray) {
			ModifyEvent.allertInvalidLuogo();
			flag = false;
		}
		if (desc.isEmpty() || desc == naal
				|| ModifyEvent.desc.getForeground() == Color.lightGray) {
			ModifyEvent.allertInvalidDesc();
			flag = false;
		}
		if (Database.Utente.getLevel() != 512) {
			Date d = ModifyEvent.cal.getDate();
			int giorno = d.getDate();
			int mese = d.getMonth() + 1;
			int anno = d.getYear() + 1900;
			// System.out.println("Data cal:"+giorno+"/"+mese+"/"+anno+" Data odierna:"+HomeCalendar.thisday+"/"+(HomeCalendar.thisMonth+1)+"/"+HomeCalendar.thisYear);
			if (anno <= HomeCalendar.thisYear)
				if (mese <= (HomeCalendar.thisMonth + 1))
					if (giorno <= HomeCalendar.thisday) {
						ModifyEvent.allertInvalidDate();
						flag = false;
					}
		}
		if (flag) {
			Evento.updateEventOnDb(id);
			HomeCalendarObserver.obs.uppdater();
			SearchEvent.evn.uppdater();
			Engine.restartHome("ModifyEvent");
		}
	}

	public static void validateRegistration() {
		String user = Registration.usertxt.getText();
		String pass = Registration.passtxt.getText();
		String nome = Registration.firstname.getText();
		String cogn = Registration.secondname.getText();
		boolean flag = true;
		if (user.length() < 4
				|| Registration.usertxt.getForeground() == Color.lightGray) {
			Registration.allertInvalidUsername();
			flag = false;
		}
		if (pass.length() < 4
				|| Registration.passtxt.getForeground() == Color.lightGray) {
			Registration.allertInvalidPassword();
			flag = false;
		}
		if (nome.length() <= 1
				|| Registration.firstname.getForeground() == Color.lightGray) {
			Registration.allertInvalidName();
			flag = false;
		}
		if (cogn.length() <= 1
				|| Registration.secondname.getForeground() == Color.lightGray) {
			Registration.allertInvalidSurname();
			flag = false;
		}
		if (flag)
			if (Database.validateRegistration(user)) {
				Registration.confirmAccountProp(true);
				Database.insertAccountOnDB(); // user è un nome disponibile e si
				// può procedere con
				// l'inserimento nel db
				Registration.stopRegistration(true);
				Login.restart(user, pass);
			} else
				Registration.allertExistingUsername(); 	// user non è disponibile
		// è si notifica a
		// Registration che
		// chiederà all'utente
		// di inserire un
		// username valido
	}

	/**
	 * Chiama il metodo removeAccount() di Account che provvede ad eliminare l'account
	 */
	public static void removeAccount() {
		Database.Utente.removeAccount();
		ModifyAccount.stopModifyAccount();
		Home.stopHome();
		startLogin();
	}

	public static void setProgress(int opz) {
		SplashScreen.setProgress(opz);
	}

	public static void stopHome() {
		Home.stopHome();
	}

	public static void pauseHome() {
		Home.pauseHome();
	}

	public static void startContactProp(int acc_id) {
		boolean flag = true;
		for (int i = 0; i < cntProp.size(); i++)
			//System.out.println("acc_id:" + acc_id + " cntProp:"+ cntProp.get(i).acc_id);
			if (cntProp.get(i).acc_id == acc_id) {
				flag = false;
				break;
			}
		if (flag)
			cntProp.add(new ContactProp(acc_id));
	}

	public static void startModifyAccount() {
		pauseHome();
		Database.accountTemp();
		new ModifyAccount();
	}

	public static void startModifyEvent(int id) {
		pauseHome();
		Database.eventoTemp(id);
		new ModifyEvent(Database.tempEvento);
	}

	public static void startCreateEvent() {
		pauseHome();
		Database.nuovoEvento();
		new CreateEvent(Database.Evento);
	}

	public static void delEvent(int id) {
		Evento.delEvent(id);
		HomeCalendarObserver.obs.uppdater();
	}

	public static void updateEvent(int id) {
		Evento.updateEventOnDb(id);
		HomeCalendarObserver.obs.uppdater();
	}

	public static void startRegistration() {
		Login.pauseLogin();
		Database.accountUtenteTemp();
		new Registration();
	}

	public static void rimuoviContatto(int id) {
		Database.Utente.removeContact(id);
	}

	public static void aggiungiContatto(int id) {
		Database.Utente.addContact(id);
	}

	public static void closeContactProp(int acc_id) {
		activeCntProp = acc_id;
		restartHome("closeContactProp");
	}

	public static void updateUnread(Vector<Integer> idUnread) {
		Notifica.updateNotificaOnDb(idUnread);
	}

	public static void setText(int maxTyped, KeyEvent e, String permitted){
		//System.out.println("char value : "+e.getKeyCode());
		if (e.getKeyCode()!=37 && e.getKeyCode()!=39 && e.getKeyCode()!=15 && e.getKeyCode()!=17){
			String testo = "";
			String car;
			String txt;
			Boolean tecst;
			try {
				txt = ((JTextField) e.getSource()).getText();
				tecst = (true);
			} catch (Exception e1) {
				txt = ((JTextArea) e.getSource()).getText();
				tecst = (false);
			}
			if (!txt.isEmpty()) {
				int m = txt.length();
				if (m > maxTyped)
					m = maxTyped;
				for (int i = 0; i < m; i++) {
					car = "" + txt.charAt(i);

					if (car.matches(permitted)) {
						if (tecst)
							if ((((JTextField) e.getSource()).getName()) == "provincia_txt")
								car = car.toUpperCase();

						testo += car;
						car = "";

					}
				}
				try {
					((JTextField) e.getSource()).setText(testo);
				} catch (Exception e1) {
					((JTextArea) e.getSource()).setText(testo);
				}
				if (txt.length() > maxTyped) {
					try {
						((JTextField) e.getSource()).setText(testo);
					} catch (Exception e1) {
						((JTextArea) e.getSource()).setText(testo);
					}
					java.awt.Toolkit.getDefaultToolkit().beep();
				}
			}
			((JComponent) e.getSource()).requestFocus();
		}
	}

	public static void sendAlert(String message, Integer acc_id) {
		new Notifica(message, "" + acc_id);
	}

	public static void pauseMenu() {
		Menu.pauseMenu();

	}

	public static void restartMenu() {
		Menu.restartMenu();
	}

}
